package com.imooc.bilibili.util;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.imooc.bilibili.exception.ConditionException;

import java.util.Calendar;
import java.util.Date;

/**
 * 生成用户令牌
 */
public class TokenUtil {

    private static final String ISSUER = "签发者";

    /**
     * 生成访问token
     *
     * @param userId
     * @return
     * @throws Exception
     */
    public static String generateToken(Long userId) throws Exception {
        // 使用RSA算法进行加密
        Algorithm algorithm = Algorithm.RSA256(RSAUtil.getPublicKey(), RSAUtil.getPrivateKey());
        // 日历类
        Calendar calendar = Calendar.getInstance();
        // 设置当前系统时间
        calendar.setTime(new Date());
        // token设置当前时间的1小时之后过期
        calendar.add(Calendar.HOUR, 1);
        // withKeyId：可以用来存储用户id字段
        return JWT.create().withKeyId(String.valueOf(userId))
                // 签发者
                .withIssuer(ISSUER)
                // 过期时间
                .withExpiresAt(calendar.getTime())
                // 使用加密算法生成签名
                .sign(algorithm);
    }

    /**
     * 生成刷新token
     *
     * @param userId
     * @return
     * @throws Exception
     */
    public static String generateRefreshToken(Long userId) throws Exception {
        Algorithm algorithm = Algorithm.RSA256(RSAUtil.getPublicKey(), RSAUtil.getPrivateKey());
        // 日历类
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        // 刷新token有效时长为7天
        calendar.add(Calendar.DAY_OF_MONTH, 7);
        return JWT.create().withKeyId(String.valueOf(userId))
                // 签发者
                .withIssuer(ISSUER)
                // 过期时间
                .withExpiresAt(calendar.getTime())
                // 使用加密算法生成签名
                .sign(algorithm);
    }

    /**
     * 验证token令牌
     *
     * @param token
     * @return 返回 userId
     */
    public static Long verifyToken(String token) {
        try {
            // 使用RSA算法进行解密
            Algorithm algorithm = Algorithm.RSA256(RSAUtil.getPublicKey(), RSAUtil.getPrivateKey());
            // 通过RSA算法生成验证类
            JWTVerifier verifier = JWT.require(algorithm).build();
            // 通过验证类将传过来的token进行验证，生成解密后的JWT
            DecodedJWT jwt = verifier.verify(token);
            // 通过JWT获取到用户id
            String userId = jwt.getKeyId();
            return Long.valueOf(userId);
        } catch (TokenExpiredException e) {
            throw new ConditionException("555", "token过期！");
        } catch (Exception e) {
            throw new ConditionException("非法用户token！");
        }
    }

}
